package controllers;

import java.util.List;

import models.ActorColegio;
import models.Colegio;
import models.Coordinador;
import models.Grado;
import models.Materia;
import models.MateriaGrado;
import models.MateriaGradoId;
import models.Orientador;
import models.Profesor;
import models.Secretario;
import play.db.jpa.Transactional;
import play.libs.Json;
import play.mvc.Controller;
import play.mvc.Result;
import services.ColegioProcessSrv;
import services.ColegioSrv;
import services.DAO;
import util.annotations.NamedAction;

public class SuperadminCtrl extends Controller {

	@Transactional
	@NamedAction("goNext")
	public static Result goNext(Long idColegio) throws InstantiationException,
			IllegalAccessException {
		Colegio c = ColegioSrv.getColegio(idColegio);
		List<String> s = ColegioProcessSrv.goNext(c);
		return ok(Json.toJson(s));
	}

	@Transactional(readOnly = true)
	@NamedAction("read")
	public static Result getColegios() {

		return ok(Json.toJson(ColegioSrv.getColegios()));
	}

	@Transactional(readOnly = true)
	@NamedAction("read")
	public static Result getColegio(Long idColegio) {

		return ok(Json.toJson(ColegioSrv.getColegio(idColegio)));
	}

	@Transactional
	@NamedAction("newColegio")
	public static Result newColegio() throws InstantiationException,
			IllegalAccessException {

		Colegio c = Json.fromJson(request().body().asJson(), Colegio.class);
		DAO.persist(c);
		DAO.flush();
		ColegioProcessSrv.startProcess(c);
		return ok(Json.toJson(c));
	}

	@Transactional(readOnly = true)
	@NamedAction("read")
	public static Result getProfesores(Long idColegio) {

		return getActores(Profesor.class, idColegio);
	}

	@Transactional(readOnly = true)
	@NamedAction("read")
	public static Result getOrientadores(Long idColegio) {

		return getActores(Orientador.class, idColegio);
	}

	@Transactional(readOnly = true)
	@NamedAction("read")
	public static Result getSecretarios(Long idColegio) {

		return getActores(Secretario.class, idColegio);
	}

	@Transactional(readOnly = true)
	@NamedAction("read")
	public static Result getCoordinadores(Long idColegio) {

		return getActores(Coordinador.class, idColegio);
	}

	private static Result getActores(Class<? extends ActorColegio> clazz,
			Long idColegio) {
		return ok(Json.toJson(DAO.query(clazz, -1, "idColegio", idColegio)));
	}

	@Transactional
	@NamedAction("newProfesor")
	public static Result newProfesor(Long idColegio) {

		Profesor c = Json.fromJson(request().body().asJson(), Profesor.class);
		c.setIdColegio(idColegio);
		ColegioSrv.crearActorConUsuario(c);

		return ok(Json.toJson(c));
	}

	@Transactional
	@NamedAction("newOrientador")
	public static Result newOrientador(Long idColegio) {
		Orientador c = Json.fromJson(request().body().asJson(),
				Orientador.class);
		c.setIdColegio(idColegio);
		ColegioSrv.crearActorConUsuario(c);
		return ok(Json.toJson(c));
	}

	@Transactional
	@NamedAction("newSecretario")
	public static Result newSecretario(Long idColegio) {
		Secretario c = Json.fromJson(request().body().asJson(),
				Secretario.class);
		c.setIdColegio(idColegio);
		ColegioSrv.crearActorConUsuario(c);
		return ok(Json.toJson(c));
	}

	@Transactional
	@NamedAction("newCoordinador")
	public static Result newCoordinador(Long idColegio) {
		Coordinador c = Json.fromJson(request().body().asJson(),
				Coordinador.class);
		c.setIdColegio(idColegio);
		ColegioSrv.crearActorConUsuario(c);
		return ok(Json.toJson(c));
	}

	@Transactional
	@NamedAction("newMateriaColegio")
	public static Result newMateriaColegio() {
		Materia mc = Json.fromJson(request().body().asJson(), Materia.class);
		DAO.persist(mc);
		DAO.flush();
		return ok(Json.toJson(mc));
	}

	@Transactional
	@NamedAction("newGradoColegio")
	public static Result newGradoColegio() {
		System.out.println(request().body().asJson());
		Grado mc = Json.fromJson(request().body().asJson(), Grado.class);
		DAO.persist(mc);
		DAO.flush();
		return ok(Json.toJson(mc));
	}

	@Transactional
	@NamedAction("deleteMateriaColegio")
	public static Result deleteMateriaColegio(Long idMateria, Long idColegio) {
		Materia mc = DAO.find(Materia.class, idMateria);

		if (mc != null && mc.getIdColegio() == idColegio)
			DAO.remove(mc);
		return ok();
	}

	@Transactional
	@NamedAction("deleteGradoColegio")
	public static Result deleteGradoColegio(Long idGrado, Long idColegio) {
		Grado mc = DAO.find(Grado.class, idGrado);
		if (mc != null && mc.getIdColegio() == idColegio)
			DAO.remove(mc);
		return ok();
	}

	@Transactional(readOnly = true)
	@NamedAction("deleteMateriasColegio")
	public static Result getMateriasColegio(Long idColegio) {
		return ok(Json.toJson(ColegioSrv.getMateriasColegio(idColegio)));
	}

	@Transactional(readOnly = true)
	@NamedAction("read")
	public static Result getGradosColegio(Long idColegio) {
		return ok(Json.toJson(ColegioSrv.getGradosColegio(idColegio)));
	}

	@Transactional(readOnly = true)
	@NamedAction("read")
	public static Result getGrado(Long idGrado) {
		return ok(Json.toJson(DAO.find(Grado.class, idGrado)));
	}

	@Transactional
	@NamedAction("updateGrado")
	public static Result updateGrado(Long idGrado) {
		System.out.println(request().body().asJson());
		Grado g = Json.fromJson(request().body().asJson(), Grado.class);
		DAO.merge(g);
		return ok();
	}

	@Transactional(readOnly = true)
	@NamedAction("read")
	public static Result getMateriasGrado(Long idGrado, Long idColegio) {
		List<Materia> m = DAO
				.execute(
						"SELECT m FROM Materia m, MateriaGrado mc WHERE mc.idMateria=m.id AND mc.idGrado=:idGrado AND mc.idColegio=:idColegio",
						-1, "idGrado", idGrado, "idColegio", idColegio);
		return ok(Json.toJson(m));
	}

	@Transactional
	@NamedAction("newMateriaGrado")
	public static Result newMateriaGrado() {
		MateriaGrado mc = Json.fromJson(request().body().asJson(),
				MateriaGrado.class);

		DAO.merge(mc);
		return ok();
	}

	@Transactional
	@NamedAction("deleteMateriaGrado")
	public static Result deleteMateriaGrado(Long idMateria, Long idGrado,
			Long idColegio) {
		MateriaGrado mc = DAO.find(MateriaGrado.class, new MateriaGradoId(
				idMateria, idColegio, idGrado));
		if (mc != null)
			DAO.remove(mc);
		return ok();
	}

}

class Asd<BodyType, ResponseType> {

	public ResponseType apply(BodyType body) {
		return null;
	}
}